Disk Formatter Routine

Apple II Technical Notes
____________________________________________________________________________
                      Developer Technical Support
Pascal #12:    Disk Formatter Routine

Revised by:    Cheryl Ewy, Dan Strnad                          
November 1988
Revised by:    Cheryl Ewy                                           June 1985

This Technical Note documents the Apple II Pascal 1.3 Disk Formatter routine.
_____________________________________________________________________________


Introduction

Integrating the Pascal Disk Formatter utility into your application program
will free the user from having to format Pascal disks prior to running 
your20
program.  Error codes that specify any problems encountered during the 
formatting process are returned.  The disk contains the following files:

FORMATTER.TEXT is a sample Pascal host program that illustrates the use
of the
formatter routine.

FORMDISK.TEXT is an assembly language function that is linked to your 
Pascal20
host program.  It contains the code to format disks in ProDOS blocked 
devices20
and calls the ASMFORMAT function to format disks in Disk II drives.

ASMFORMAT.TEXT is the Disk II formatter, an assembly language procedure 
that20
must be specially handled (see below).

BOOTTRACKS.DATA is a data file that is used to create the formatter data 
file. 20
It contains boot blocks for both Disk II drives and ProDOS blocked 
devices and20
a blank disk directory.

MAKEFMT.TEXT, MAKEFMT.CODE are a Pascal program that will create the 
required20
formatter data file.

FORMATTER.DATA is a complete formatter data file (identical to that 
supplied20
with the Apple II Pascal 1.3 Development System).

FORMATTER.CODE is the formatter program supplied with the Apple II 
Pascal 1.320
Development System.

All programs are supplied in source (and where appropriate, as code 
files) so20
that you may modify them for your own particular purposes.


ASMFORMAT - The Disk II Formatter Routine

The file ASMFORMAT.TEXT contains a proprietary subroutine that performs 
the20
actual formatting of Disk II disks.  It is written in 6502 assembly 
language20
suitable for assembly by the Apple II or Apple /// Pascal Assembler.  
This20
code requires special handling by the host program to ensure a reliable20
format.  It contains critical timing code, and because of this, it must 
be20
located on a page boundary in memory (a location of the form xx00, e.g., 
3D00,20
2000, etc.).  To do this, it must be assembled ABSOLUTE and you must use 
ORG20
to place it on particular page boundary.  It comes supplied at location 
3D00,20
which is the location used by the formatter routine supplied with the 
Apple II20
Pascal 1.3 Development System (FORMATTER.CODE).  If you need to move it 
to20
another particular location you must change the .ORG statement in the 
file to20
the new address.  The formatter will not work reliably if it is not on a 
page20
boundary.  The code itself is 1082 bytes in length.

Because of the special nature of this code, it must be loaded by the 
Pascal20
host program at the chosen location.  The following sample code 
illustrates20
how this is done:

    TYPE MEMARRAY =3D PACKED ARRAY [0..1535] OF 0..255;

        MEMPTR =3D RECORD CASE BOOLEAN OF
                TRUE:  (ADDR: INTEGER);
                FALSE: (MEM: ^MEMARRAY);
            END;

    VAR  LOADPTR: MEMPTR;     {this is the pointer to the absolute
memory
                              location where the Disk II formatter 
routine
                              will be loaded.}


        {the following code will load the Disk II formatter routine
        from the formatter data file into memory at a fixed location}

        RESET(DATAFILE, '%FORMATTER.DATA');

        LOADPTR.ADDR :=3D 15616;    {this value is the absolute memory 
location
                                  where the code is to be loaded.  In 
this
                                  example, 15316 is the decimal =
equivalent of
                                  the memory address 3D00.}

        BLOCKSREAD :=3D BLOCKREAD(DATAFILE, LOADPTR.MEM^, 3);
{the above line will load three blocks (the Disk II formatter code) from 
the data file into
the memory space specified in LOADPTR}

The Disk II formatter routine assumes that the A register has been setup 
with
the slot number and drive number of the disk which is to be formatted. 
FORMDISK sets up this information before doing a JSR to the Disk II 
formatter
routine.  The contents of the A register are defined as follows:

    Bit 7       Drive number.  03DDrive 1, 13DDrive 2
    Bits 6-4    Slot number.  1003D4, 1013D5, 1103D6.  No other slots 
are
                              supported.
    Bits 3-0    Reserved; must be set to zero.

After the Disk II formatter routine is called, it returns an error code 
in the
A register.  FORMDISK then returns this error code to the host program.  
The
error codes are listed in the following section.


FORMDISK - The Main Formatter Routine

The file FORMDISK.TEXT is an assembly language function that is 
assembled and
linked to your Pascal host program.  This function determines whether 
the
drive containing the disk to be formatted is a Disk II drive or a ProDOS 

blocked device.  If it is a Disk II drive, FORMDISK invokes the Disk II
formatter routine with the required parameters as described in the 
previous
section.  If the drive is a ProDOS blocked device, FORMDISK sets up the 
proper
parameters and executes a format call to the device.  FORMDISK will 
return an
error code back to the Pascal host after the formatting is complete.  
The call
to this function is shown below:

     VAR  ERRCODE: INTEGER;            {the error code returned}
          VOLNUM:  INTEGER;            {the volume (unit) number of the =
disk}
     ERRCODE :=3D FORMDISK(VOLNUM);      {the function call}

There are six possible error codes returned by FORMDISK.  They indicate
problems that may have occurred during the formatting process.  They are 
as
follows:

Error code  Error                        Possible causes
_________________________________________________________________________
____
00          No Error                     Formatting successfully 
completed

39          Unable to format the disk    No disk in drive; drive door 
not
                                         closed; bad media

43          Disk is write-protected      Disk is write-protected; disk 
is
                                         pushed halfway into drive,
                                         activating the write-protect 
switch

47          No disk in drive             The disk drive is empty.  This 
error
                                         is only reported for ProDOS 
block
                                         devices.  If a Disk II drive is 
empty,
                                         error #39 is returned.

51          Drive speed is too slow      The drive motor speed requires
                                         adjustment, it is too slow.  
This
                                         erroris only reported for Disk 
IIs.

52          Drive speed is too fast      The drive motor speed requires
                                         adjustment, it is too fast.  
This
                                         error is only reported for Disk 
IIs.

To use the FORMDISK function requires that you modify one .EQU statement 
in 
the source file (FORMDISK.TEXT) to specify the location of the Disk II
formatter routine in memory.  Currently, the statement reads as follows:

    DO_FORMAT   .EQU   3D00   ;memory address of the Disk II formatter 
routine

If you decide to relocate the Disk II formatter routine, simply change 
this
value to reflect the new memory address, then reassemble FORMDISK.  The
FORMDISK function does a JSR to this value to invoke the Disk II 
formatter
routine.

Note:    The value used in the .ORG in ASMFORMAT and the .EQU in
FORMDISK must match.


Making a Formatter Data File

To use the formatter requires a data file that contains three pieces:

1.    The Disk II formatter routine code, to be loaded into memory.
2.    The boot code that is written to blocks 0 and 1 of the formatted
      disk.
3.    A blank UCSD Pascal directory that is written to block 2 of the
      formatted disk.

The formatter disk comes with the second and third parts in the file
BOOTTRACKS.DATA.  This four-block file contains the boot blocks for Disk 
II
drives and ProDOS blocked devices and the blank directory.  Once the 
Disk II
formatter routine has been assembled (to ASMFORMAT.CODE) it must be
concatenated to the BOOTTRACKS.DATA file to make the formatter data 
file.  The
Disk II formatter routine code occupies the first 3 blocks of the 
formatter
data file, which is then followed by the contents of the BOOTTRACKS.DATA 
file. 
Because the assembler puts special informational content blocks into a 
code
file, a special program is required to copy only the blocks containing 
the
code of the Disk II formatter routine.  This is the program 
MAKEFMT.CODE. 
This program copies blocks 1, 2, and 3 of ASMFORMAT.CODE to blocks 0, 1, 
and 2
of the file FORMATTER.DATA.  It then copies blocks 0, 1, 2, and 3 of the 
file
BOOTTRACKS.DATA to blocks 3, 4, 5, and 6 of the file FORMATTER.DATA.  
This
makes the required formatter data file (7 blocks in size) that will be 
used by
the Pascal host program.  MAKEFMT requires that the files ASMFORMAT.CODE 
and
BOOTTRACKS.DATA be on the prefix volume.  Set the Pascal prefix to this 
volume
and X(ecute MAKEFMT.  It will create the file FORMATTER.DATA on the same 

volume.  The source for this program is included so that you may modify 
it as
needed.


The Pascal Host Program

It is up to you to write the Pascal host program.  On the disk is a 
sample
program (the Apple II Pascal 1.3 Formatter) that you may study.  It
illustrates the above techniques.  The primary functions of the Pascal 
host
are to:

1.    Open the FORMATTER.DATA file.
2.    Read blocks 0 - 2 into a memory location that is on a page
      boundary.
3.    Read blocks 3 - 6 into a 2,048 byte buffer.
4.    Call the assembly language function FORMDISK with the volume
      number of the drive containing the disk to be formatted.
5.    Examine the error code returned.  If there is an error then report 

      it to the user, otherwise continue.
6.    Use UNITSTATUS to determine whether the drive is a Disk II or a
      ProDOS blocked device and how many blocks are on the disk.
7.    Use the number of blocks returned by UNITSTATUS to update the
      maximum block number information in the blank directory.
8.    If the drive is a Disk II, use UNITWRITE to write blocks 0 - 2
      from the buffer to blocks 0 - 2 on the newly formatted disk.
9.    If the drive is a ProDOS blocked device, use UNITWRITE to write
      block 3 from the buffer to block 0 on the newly formatted disk,
      then use it again to write block 2 from the buffer to block 2 on
      the disk.

The following code is an example of how to read in the blocks from the
FORMATTER.DATA file, determine the drive type, update the directory, and 
write
the boot blocks and directory to the newly formatted disk:

    TYPE BYTARRAY =3D PACKED ARRAY [0..1] OF 0..255;

    VAR  BUFFER: PACKED ARRAY [0..2048] OF 0..255;

    NUMBLOCKS : INTEGER;

    TRIX : RECORD CASE BOOLEAN OF
                TRUE  : (INT : INTEGER);
                FALSE : (BYT : BYTARRAY);
            END;

    {read in the boot blocks and directory}
    NUMBLOCKS :=3D BLOCKREAD (DATAFILE, BUFFER, 4, 3);

    {determine type of disk drive and number of blocks on the disk}
    UNITSTATUS (VOLNUM, NUMBLOCKS, 1);

    {update maximum number of blocks in blank directory}
    TRIX.INT :=3D NUMBLOCKS;
    BUFFER[1038] :=3D TRIX.BYT[0];
    BUFFER[1039] :=3D TRIX.BYT[1];

    {write out the boot blocks and directory to a Disk II disk}
    UNITWRITE (VOLNUM, BUFFER, 1536, 0);

    {write out the boot block and directory to a ProDOS blocked device disk}
    UNITWRITE (VOLNUM, BUFFER[1536], 512, 0);
    UNITWRITE (VOLNUM, BUFFER[1024], 512, 2);

A dynamic variable can also be used as the buffer so that your program can
reclaim the buffer space for its own use after the formatting is 
completed:

    TYPE BUFFER =3D PACKED ARRAY [0..2048] OF 0..255;

    VAR BUFPTR : ^BUFFER;
    OLDPTR : ^INTEGER;

     {mark the beginning of usable space}
    MARK (OLDPTR);
     {allocate space for the buffer}
    NEW (BUFPTR);
     {read in the boot blocks and directory}
    NUMBLOCKS :=3D BLOCKREAD (DATAFILE, BUFPTR^, 4, 3);
    {write out the boot blocks and directory to a Disk II disk}
    UNITWRITE (VOLNUM, BUFPTR^, 1536, 0);
    {release the space used by the buffer}
    RELEASE (OLDPTR);


In Review

The following is a step-by-step review of how to use the formatting 
routine.

 1.    Determine where in memory you wish to load the Disk II formatter
       routine.  Remember it must be on a page boundary.
 2.    Edit the file ASMFORMAT.TEXT, and change the value in the .ORG
       statement to be the memory address chosen.
 3.    Assemble ASMFORMAT.TEXT to ASMFORMAT.CODE.
 4.    X(ecute MAKEFMT to make the required FORMATTER.DATA file.
 5.    Edit the file FORMDISK.TEXT and change the line

           DO_FORMAT   .EQU   3D00

       to reflect the new memory location (same value as in the .ORG
       statement  above).
 6.    Assemble FORMDISK.TEXT to FORMDISK.CODE.
 7.    Write the Pascal host program using the above techniques for
       loading the Disk II formatter routine, calling the FORMDISK
       function, updating the blank directory, and writing the boot
       blocks and directory.  Remember error reporting.
 8.    Compile the Pascal host.
 9.    Link the Pascal host to the file FORMDISK.CODE, thus linking the
       FORMDISK function into your program.
10.    With the linked Pascal host program and the FORMATTER.DATA file
       you can now format disks.